using Net35.Xrm.Sdk.Client;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Security;
namespace Net35.Xrm.Sdk
{
	internal abstract class KnownProxyTypesProvider
	{
		private static AppDomainBasedKnownProxyTypesProvider _appDomainBasedInstance;
		private static AssemblyBasedKnownProxyTypesProvider _assemblyBasedInstance;
		private static object _lockObject;
		protected List<Assembly> _strongTypeAssemblies;
		protected static Dictionary<Type, string> _typeAttributes;
		protected static object ThisLock
		{
			get
			{
				return KnownProxyTypesProvider._lockObject;
			}
		}
		static KnownProxyTypesProvider()
		{
			KnownProxyTypesProvider._appDomainBasedInstance = null;
			KnownProxyTypesProvider._assemblyBasedInstance = null;
			KnownProxyTypesProvider._lockObject = new object();
			KnownProxyTypesProvider._typeAttributes = new Dictionary<Type, string>();
			KnownProxyTypesProvider._typeAttributes.Add(typeof(EntityLogicalNameAttribute), "LogicalName");
			KnownProxyTypesProvider._typeAttributes.Add(typeof(ResponseProxyAttribute), "Name");
		}
		[SecuritySafeCritical]
		protected KnownProxyTypesProvider()
		{
			this._strongTypeAssemblies = new List<Assembly>();
		}
		protected abstract void AddTypeMapping(Assembly assembly, Type type, string proxyName);
		public abstract Type GetTypeForName(string name, Assembly proxyTypesAssembly);
		public abstract string GetNameForType(Type type);
		protected abstract void OnBeginLoadTypes(Assembly targetAssembly);
		protected abstract void OnEndLoadTypes();
		protected abstract void OnErrorLoadTypes();
		internal static KnownProxyTypesProvider GetInstance(bool supportIndividualAssemblies)
		{
			if (supportIndividualAssemblies)
			{
				if (KnownProxyTypesProvider._assemblyBasedInstance == null)
				{
					lock (KnownProxyTypesProvider._lockObject)
					{
						if (KnownProxyTypesProvider._assemblyBasedInstance == null)
						{
							KnownProxyTypesProvider._assemblyBasedInstance = new AssemblyBasedKnownProxyTypesProvider();
						}
					}
				}
				return KnownProxyTypesProvider._assemblyBasedInstance;
			}
			if (KnownProxyTypesProvider._appDomainBasedInstance == null)
			{
				lock (KnownProxyTypesProvider._lockObject)
				{
					if (KnownProxyTypesProvider._appDomainBasedInstance == null)
					{
						KnownProxyTypesProvider._appDomainBasedInstance = new AppDomainBasedKnownProxyTypesProvider();
					}
				}
			}
			return KnownProxyTypesProvider._appDomainBasedInstance;
		}
		public void RegisterAssembly(string assemblyName)
		{
			Assembly assembly = Assembly.Load(assemblyName);
			this.RegisterAssembly(assembly);
		}
		public void RegisterAssembly(Assembly assembly)
		{
			if (this._strongTypeAssemblies.Contains(assembly))
			{
				return;
			}
			lock (KnownProxyTypesProvider._lockObject)
			{
				if (!this._strongTypeAssemblies.Contains(assembly))
				{
					this._strongTypeAssemblies.Add(assembly);
					this.LoadKnownTypes(assembly);
				}
			}
		}
		private void LoadKnownTypes(Assembly assembly)
		{
			object[] customAttributes = assembly.GetCustomAttributes(typeof(ProxyTypesAssemblyAttribute), false);
			if (customAttributes == null || customAttributes.Length == 0)
			{
				return;
			}
			this.OnBeginLoadTypes(assembly);
			try
			{
				Type[] exportedTypes = assembly.GetExportedTypes();
				for (int i = 0; i < exportedTypes.Length; i++)
				{
					Type type = exportedTypes[i];
					foreach (KeyValuePair<Type, string> current in KnownProxyTypesProvider._typeAttributes)
					{
						object[] customAttributes2 = type.GetCustomAttributes(current.Key, false);
						if (customAttributes2 != null && customAttributes2.Length > 0 && customAttributes2[0].GetType().GetProperty(current.Value) != null)
						{
							string proxyName = (string)customAttributes2[0].GetType().GetProperty(current.Value).GetValue(customAttributes2[0], null);
							this.AddTypeMapping(assembly, type, proxyName);
						}
					}
				}
				this.OnEndLoadTypes();
			}
			catch
			{
				this.OnErrorLoadTypes();
				throw;
			}
		}
		protected void InitializeLoadedAssemblies()
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Assembly assembly = assemblies[i];
				this.RegisterAssembly(assembly);
			}
		}
	}
}
